package com.hello.gen.controller;

import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.hello.common.core.text.Convert;
import com.hello.common.core.utils.StringUtils;
import com.hello.common.core.web.controller.BaseController;
import com.hello.common.core.web.domain.AjaxResult;
import com.hello.common.core.web.page.TableDataInfo;
import com.hello.common.log.annotation.Log;
import com.hello.common.log.enums.BusinessType;
import com.hello.common.security.annotation.RequiresPermissions;
import com.hello.gen.domain.GenTable;
import com.hello.gen.domain.GenTableColumn;
import com.hello.gen.service.IGenTableColumnService;
import com.hello.gen.service.IGenTableService;
import lombok.RequiredArgsConstructor;
import java.net.InetAddress;
import com.alibaba.fastjson.JSON;
import com.hello.common.core.exception.ServiceException;
import com.hello.common.core.constant.GenConstants;

/**
 * 代码生成 操作处理
 * 
 * @author hello
 */
@RequestMapping("/gen")
@RestController
@RequiredArgsConstructor
public class GenController extends BaseController
{
    private static final Logger log = LoggerFactory.getLogger(GenController.class);
    
    private final IGenTableService genTableService;

    private final IGenTableColumnService genTableColumnService;

    /**
     * 查询代码生成列表
     */
    @RequiresPermissions("tool:gen:list")
    @GetMapping("/list")
    public TableDataInfo genList(GenTable genTable)
    {
        // 确保params不为null
        if (genTable.getParams() == null)
        {
            genTable.setParams(new HashMap<>());
        }
        startPage();
        List<GenTable> list = genTableService.selectGenTableList(genTable);
        return getDataTable(list);
    }

    /**
     * 修改代码生成业务
     */
    @RequiresPermissions("tool:gen:query")
    @GetMapping(value = "/{tableId}")
    public AjaxResult getInfo(@PathVariable Long tableId)
    {
        GenTable table = genTableService.selectGenTableById(tableId);
        List<GenTable> tables = genTableService.selectGenTableAll();
        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("info", table);
        map.put("rows", list);
        map.put("tables", tables);
        return success(map);
    }

    /**
     * 查询数据库列表
     */
    @RequiresPermissions("tool:gen:list")
    @GetMapping("/db/list")
    public TableDataInfo dataList(GenTable genTable)
    {
        // 确保params不为null
        if (genTable.getParams() == null)
        {
            genTable.setParams(new HashMap<>());
        }
        startPage();
        List<GenTable> list = genTableService.selectDbTableList(genTable);
        return getDataTable(list);
    }

    /**
     * 查询数据表字段列表
     */
    @GetMapping(value = "/column/{tableId}")
    public TableDataInfo columnList(Long tableId)
    {
        TableDataInfo dataInfo = new TableDataInfo();
        List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
        dataInfo.setRows(list);
        dataInfo.setTotal(list.size());
        return dataInfo;
    }

    /**
     * 导入表结构（保存）
     */
    @RequiresPermissions("tool:gen:import")
    @Log(title = "代码生成", businessType = BusinessType.IMPORT)
    @PostMapping("/importTable")
    public AjaxResult importTableSave(String tables)
    {
        log.info("收到导入表请求，表名列表: {}", tables);
        String[] tableNames = Convert.toStrArray(tables);
        log.info("准备导入{}个表", tableNames.length);
        // 查询表信息
        List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
        log.info("从数据库查询到{}个表信息", tableList.size());
        genTableService.importGenTable(tableList);
        log.info("表导入成功");
        return success();
    }

    /**
     * 修改保存代码生成业务
     */
    @RequiresPermissions("tool:gen:edit")
    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
    {
        // 记录接收到的表单数据
        log.info("======接收到表单保存请求======");
        log.info("表ID: {}", genTable.getTableId());
        log.info("表名: {}", genTable.getTableName());
        log.info("表类型: {}", genTable.getTplCategory());
        
        // 记录合并模式信息
        String mergeMode = "未设置";
        if (genTable.getParams() != null && genTable.getParams().containsKey("mergeMode")) {
            mergeMode = genTable.getParams().get("mergeMode").toString();
        } else if (genTable.getMergeMode() != null) {
            mergeMode = genTable.getMergeMode();
        }
        log.info("合并模式: {}", mergeMode);
        
        // 记录上级菜单信息
        String parentMenuId = "未设置";
        String parentMenuName = "未设置";
        
        if (genTable.getParams() != null) {
            if (genTable.getParams().containsKey("parentMenuId")) {
                parentMenuId = genTable.getParams().get("parentMenuId").toString();
            }
            
            if (genTable.getParams().containsKey("parentMenuName")) {
                parentMenuName = genTable.getParams().get("parentMenuName").toString();
            }
            
            log.info("参数信息: {}", JSON.toJSONString(genTable.getParams()));
        }
        
        log.info("上级菜单ID: {}", parentMenuId);
        log.info("上级菜单名称: {}", parentMenuName);
        
        genTableService.validateEdit(genTable);
        genTableService.updateGenTable(genTable);
        return success();
    }

    /**
     * 删除代码生成
     */
    @RequiresPermissions("tool:gen:remove")
    @Log(title = "代码生成", businessType = BusinessType.DELETE)
    @DeleteMapping("/{tableIds}")
    public AjaxResult remove(@PathVariable Long[] tableIds)
    {
        genTableService.deleteGenTableByIds(tableIds);
        return success();
    }

    /**
     * 预览代码
     */
    @RequiresPermissions("tool:gen:preview")
    @GetMapping("/preview/{tableId}")
    public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
    {
        Map<String, String> dataMap = genTableService.previewCode(tableId);
        return success(dataMap);
    }

    /**
     * 生成代码（下载方式）
     */
    @RequiresPermissions("tool:gen:code")
    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
    @GetMapping("/download/{tableName}")
    public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
    {
        byte[] data = genTableService.downloadCode(tableName);
        genCode(response, data);
    }

    /**
     * 生成代码（自定义路径）
     */
    @RequiresPermissions("tool:gen:code")
    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
    @GetMapping("/genCode/{tableName}")
    public AjaxResult genCode(@PathVariable("tableName") String tableName, 
                             @RequestParam(value = "genPath", required = false) String genPath,
                             @RequestParam(value = "mergeMode", required = false) String mergeMode,
                             @RequestParam(value = "parentMenuId", required = false) String parentMenuId,
                             @RequestParam(value = "parentMenuName", required = false) String parentMenuName)
    {
        // 查询表信息
        GenTable table = genTableService.selectGenTableByName(tableName);
        if (table == null) {
            return error("未找到表信息，请重新检查！");
        }
        
        // 如果有合并模式参数，设置到table中
        if (StringUtils.isNotEmpty(mergeMode)) {
            log.info("使用传入的合并模式: {}", mergeMode);
            table.setMergeMode(mergeMode);
            // 同时设置到params中，确保后续保存时能够正确处理
            Map<String, Object> params = table.getParams() != null ? table.getParams() : new HashMap<>();
            params.put("mergeMode", mergeMode);
            table.setParams(params);
        }
        
        // 如果有上级菜单参数，设置到table中
        if (StringUtils.isNotEmpty(parentMenuId) && StringUtils.isNotEmpty(parentMenuName)) {
            log.info("使用传入的上级菜单ID: {}, 上级菜单名称: {}", parentMenuId, parentMenuName);
            table.setParentMenuId(parentMenuId);
            table.setParentMenuName(parentMenuName);
            
            // 同时设置到params中，确保后续保存时能够正确处理
            Map<String, Object> params = table.getParams() != null ? table.getParams() : new HashMap<>();
            params.put(GenConstants.PARENT_MENU_ID, parentMenuId);
            params.put(GenConstants.PARENT_MENU_NAME, parentMenuName);
            table.setParams(params);
            
            // 更新表信息
            genTableService.updateGenTable(table);
        }
        
        log.info("更新后的表信息 - 上级菜单ID: {}, 上级菜单名称: {}, 合并模式: {}", 
                table.getParentMenuId(), table.getParentMenuName(), table.getMergeMode());
        
        // 根据合并模式进行代码生成
        boolean merge = !"0".equals(table.getMergeMode()); // 0表示覆盖模式，其他值使用智能合并
        log.info("生成代码，表名：{}，路径：{}，同时生成前端和后端代码，合并模式：{}", 
                tableName, genPath, merge ? "智能合并" : "覆盖模式");
        
        try {
            genTableService.generatorCode(tableName, genPath, null, merge);
            return success();
        } catch (Exception e) {
            // 如果是业务异常，直接返回异常信息
            if (e instanceof ServiceException) {
                log.warn("生成代码时发生业务异常: {}", e.getMessage());
                return error(e.getMessage());
            }
            // 其他异常
            log.error("生成代码失败: ", e);
            return error("生成代码失败，请检查生成权限和配置！");
        }
    }

    /**
     * 检查代码文件是否存在
     */
    @RequiresPermissions("tool:gen:code")
    @GetMapping("/checkExists/{tableName}")
    public AjaxResult checkExists(@PathVariable("tableName") String tableName, 
                             @RequestParam(value = "genPath", required = false) String genPath,
                             @RequestParam(value = "mergeMode", required = false) String mergeMode)
    {
        // 查询表信息
        GenTable table = genTableService.selectGenTableByName(tableName);
        if (table == null) {
            return error("未找到表信息，请重新检查！");
        }
        
        try {
            // 调用service层方法检查文件是否存在
            List<String> existingFiles = genTableService.checkFilesExist(tableName, genPath);
            
            if (existingFiles.isEmpty()) {
                // 没有文件存在，可以生成
                return success("没有发现已存在的文件，可以生成代码");
            } else {
                // 返回存在的文件列表
                Map<String, Object> result = new HashMap<>();
                result.put("exists", true);
                result.put("fileCount", existingFiles.size());
                result.put("files", existingFiles.size() > 10 ? 
                        existingFiles.subList(0, 10) : existingFiles);
                return AjaxResult.success("发现已存在的文件", result);
            }
        } catch (Exception e) {
            log.error("检查文件是否存在时出错: ", e);
            return error("检查文件是否存在时出错: " + e.getMessage());
        }
    }

    /**
     * 删除生成的代码文件
     */
    @RequiresPermissions("tool:gen:code")
    @Log(title = "删除代码", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteCode/{tableName}")
    public AjaxResult deleteCode(@PathVariable("tableName") String tableName,
                                @RequestParam(value = "backendPath", required = false) String backendPath,
                                @RequestParam(value = "frontendPath", required = false) String frontendPath,
                                @RequestParam(value = "codeType", required = false) String codeType) {
        try {
            // 查询表信息
            GenTable table = genTableService.selectGenTableByName(tableName);
            if (table == null) {
                return error("表信息不存在");
            }
            
            // 如果未指定路径，则使用表中保存的路径
            if (StringUtils.isEmpty(backendPath)) {
                backendPath = table.getBackendGenPath();
            }
            if (StringUtils.isEmpty(frontendPath)) {
                frontendPath = table.getFrontendGenPath();
            }
            
            // 进一步检查，如果仍然为空，使用genPath
            if (StringUtils.isEmpty(backendPath)) {
                backendPath = table.getGenPath();
            }
            if (StringUtils.isEmpty(frontendPath)) {
                frontendPath = table.getGenPath();
            }
            
            // 是否删除后端代码
            boolean deleteBackend = codeType == null || "backend".equals(codeType);
            // 是否删除前端代码
            boolean deleteFrontend = codeType == null || "frontend".equals(codeType);
            
            log.info("删除生成代码，表名：{}，后端路径：{}，前端路径：{}，代码类型：{}", 
                    tableName, backendPath, frontendPath, codeType == null ? "全部" : codeType);
            
            // 构建需要删除的文件清单
            List<String> filePaths = new ArrayList<>();
            
            // 1. 构建Java相关文件路径
            String packagePath = StringUtils.replace(table.getPackageName(), ".", "/");
            String className = table.getClassName();
            String businessName = table.getBusinessName();
            String moduleName = table.getModuleName();
            
            // 后端代码路径
            if (deleteBackend && StringUtils.isNotEmpty(backendPath)) {
                // Domain文件
                filePaths.add(String.format("%s/src/main/java/%s/domain/%s.java", backendPath, packagePath, className));
                // Mapper接口
                filePaths.add(String.format("%s/src/main/java/%s/mapper/%sMapper.java", backendPath, packagePath, className));
                // Service接口
                filePaths.add(String.format("%s/src/main/java/%s/service/I%sService.java", backendPath, packagePath, className));
                // ServiceImpl
                filePaths.add(String.format("%s/src/main/java/%s/service/impl/%sServiceImpl.java", backendPath, packagePath, className));
                // Controller
                filePaths.add(String.format("%s/src/main/java/%s/controller/%sController.java", backendPath, packagePath, className));
                // Mapper XML
                filePaths.add(String.format("%s/src/main/resources/mapper/%s/%sMapper.xml", backendPath, moduleName, className));
            }
            
            // 前端代码路径
            if (deleteFrontend && StringUtils.isNotEmpty(frontendPath)) {
                // API JS文件
                filePaths.add(String.format("%s/src/api/%s/%s.js", frontendPath, moduleName, businessName));
                // Vue页面
                filePaths.add(String.format("%s/src/views/%s/%s/index.vue", frontendPath, moduleName, businessName));
            }
            
            // 执行删除
            int deleteCount = 0;
            for (String filePath : filePaths) {
                File file = new File(filePath);
                if (file.exists() && file.isFile()) {
                    boolean deleted = file.delete();
                    if (deleted) {
                        log.info("已删除文件: {}", filePath);
                        deleteCount++;
                    } else {
                        log.warn("无法删除文件: {}", filePath);
                    }
                } else {
                    log.info("文件不存在，无需删除: {}", filePath);
                }
            }
            
            String message = deleteCount > 0 ? 
                    String.format("删除了 %d 个%s代码文件", deleteCount, 
                            deleteBackend && deleteFrontend ? "" : 
                            (deleteBackend ? "后端" : "前端")) : 
                    "没有找到需要删除的文件";
                    
            return success(message);
        } catch (Exception e) {
            log.error("删除代码文件失败", e);
            return error("删除代码文件失败：" + e.getMessage());
        }
    }

    /**
     * 同步数据库
     */
    @RequiresPermissions("tool:gen:edit")
    @Log(title = "代码生成", businessType = BusinessType.UPDATE)
    @GetMapping("/synchDb/{tableName}")
    public AjaxResult synchDb(@PathVariable("tableName") String tableName)
    {
        genTableService.synchDb(tableName);
        return success();
    }

    /**
     * 获取表结构SQL
     */
    @GetMapping("/sql/{tableName}")
    public AjaxResult getTableSql(@PathVariable("tableName") String tableName)
    {
        log.info("接收到获取表结构SQL请求，表名: {}", tableName);
        try {
            String sql = genTableService.getTableSql(tableName);
            log.info("成功获取到表结构SQL，长度: {}", sql != null ? sql.length() : 0);
            return AjaxResult.success("获取成功", sql);
        } catch (Exception e) {
            log.error("获取表结构SQL出错: ", e);
            return AjaxResult.error("获取表结构SQL出错: " + e.getMessage());
        }
    }

    /**
     * 批量生成代码
     */
    @RequiresPermissions("tool:gen:code")
    @Log(title = "代码生成", businessType = BusinessType.GENCODE)
    @GetMapping("/batchGenCode")
    public void batchGenCode(HttpServletResponse response, String tables) throws IOException
    {
        String[] tableNames = Convert.toStrArray(tables);
        byte[] data = genTableService.downloadCode(tableNames);
        genCode(response, data);
    }

    /**
     * 生成zip文件
     */
    private void genCode(HttpServletResponse response, byte[] data) throws IOException
    {
        response.reset();
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Content-Disposition", "attachment; filename=\"hello.zip\"");
        response.addHeader("Content-Length", "" + data.length);
        response.setContentType("application/octet-stream; charset=UTF-8");
        IOUtils.write(data, response.getOutputStream());
    }

    /**
     * 获取系统目录结构
     */
    @GetMapping("/system/directories")
    public AjaxResult getSystemDirectories(String path)
    {
        try {
            File directory;
            if (StringUtils.isEmpty(path)) {
                // 获取系统根目录
                directory = new File(System.getProperty("user.dir")).getParentFile();
                // 如果是Windows系统，可能需要获取磁盘根目录列表
                if (System.getProperty("os.name").toLowerCase().contains("win")) {
                File[] roots = File.listRoots();
                    List<Map<String, String>> rootDirectories = new ArrayList<>();
                for (File root : roots) {
                        Map<String, String> rootDir = new HashMap<>();
                        rootDir.put("name", root.getAbsolutePath());
                        rootDir.put("path", root.getAbsolutePath());
                        rootDirectories.add(rootDir);
                    }
                    return success(rootDirectories);
                }
            } else {
                directory = new File(path);
            }
            
            if (!directory.exists() || !directory.isDirectory()) {
                return error("指定路径不是有效的目录");
            }

            File[] files = directory.listFiles(File::isDirectory);
            if (files == null) {
                return error("无法访问该目录");
            }

            List<Map<String, String>> directories = new ArrayList<>();
            for (File file : files) {
                Map<String, String> dir = new HashMap<>();
                dir.put("name", file.getName());
                dir.put("path", file.getAbsolutePath());
                directories.add(dir);
            }
            return success(directories);
        } catch (Exception e) {
            return error("获取目录结构失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目工作空间路径
     */
    @GetMapping("/workspace")
    public AjaxResult getWorkspace() 
    {
        Map<String, String> result = new HashMap<>();
        try {
            String workspace = System.getProperty("user.dir");
            String osName = System.getProperty("os.name");
            String userHome = System.getProperty("user.home");
            String javaHome = System.getProperty("java.home");
            
            log.info("获取工作空间路径: {}", workspace);
            log.info("操作系统: {}", osName);
            log.info("用户目录: {}", userHome);
            log.info("Java路径: {}", javaHome);
            
            result.put("workspace", workspace);
            result.put("osName", osName);
            result.put("userHome", userHome);
            result.put("javaHome", javaHome);
            
            return success(result);
        } catch (Exception e) {
            log.error("获取工作空间路径失败", e);
            return error("获取工作空间路径失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目结构信息
     */
    @GetMapping("/project-structure")
    public AjaxResult getProjectStructure() 
    {
        Map<String, Object> result = new HashMap<>();
        try {
            String workspace = System.getProperty("user.dir");
            log.info("开始扫描项目结构，根路径: {}", workspace);
            
            File rootDir = new File(workspace);
            if (!rootDir.exists() || !rootDir.isDirectory()) {
                return error("项目根目录不存在或不是一个目录");
            }
            
            // 读取根pom.xml
            File rootPom = new File(rootDir, "pom.xml");
            if (rootPom.exists()) {
                result.put("hasMavenRootPom", true);
                // 简单读取pom文件获取项目信息
                try {
                    String pomContent = readFileContent(rootPom);
                    result.put("projectName", extractXmlTag(pomContent, "artifactId"));
                    result.put("projectVersion", extractXmlTag(pomContent, "version"));
                    result.put("projectDescription", extractXmlTag(pomContent, "description"));
                } catch (Exception e) {
                    log.warn("读取根pom.xml出错", e);
                }
            } else {
                result.put("hasMavenRootPom", false);
            }
            
            // 工作空间和环境信息
            result.put("userDir", workspace);
            result.put("osName", System.getProperty("os.name"));
            result.put("osVersion", System.getProperty("os.version"));
            result.put("javaHome", System.getProperty("java.home"));
            
            // 识别项目模块
            List<Map<String, Object>> modules = new ArrayList<>();
            File[] files = rootDir.listFiles();
            
            if (files != null) {
                // 计数统计
                int moduleCount = 0;
                int javaFileCount = 0;
                int totalFileCount = 0;
                int packageCount = 0;
                
                // 查找模块（通常是包含pom.xml的目录）
                for (File file : files) {
                    if (file.isDirectory()) {
                        // 创建模块节点
                        Map<String, Object> module = createModuleNode(file);
                        if (module != null) {
                            moduleCount++;
                            javaFileCount += (int) module.getOrDefault("javaFiles", 0);
                            totalFileCount += (int) module.getOrDefault("totalFiles", 0);
                            packageCount += (int) module.getOrDefault("packageCount", 0);
                            modules.add(module);
                        }
                    }
                }
                
                result.put("modules", modules);
                result.put("moduleCount", moduleCount);
                result.put("javaFileCount", javaFileCount);
                result.put("javaPackageCount", packageCount);
                result.put("totalFileCount", totalFileCount);
                
                log.info("项目结构扫描完成，检测到{}个模块，{}个Java包，{}个Java文件，{}个总文件", 
                        moduleCount, packageCount, javaFileCount, totalFileCount);
            }
            
            return success(result);
        } catch (Exception e) {
            log.error("扫描项目结构失败", e);
            return error("扫描项目结构失败：" + e.getMessage());
        }
    }
    
    /**
     * 创建模块节点信息，包含子目录结构
     */
    private Map<String, Object> createModuleNode(File file) {
        // 检查是否是Maven模块
        File pomFile = new File(file, "pom.xml");
        if (!pomFile.exists()) {
            return null;
        }
        
        Map<String, Object> module = new HashMap<>();
        module.put("name", file.getName());
        module.put("path", file.getAbsolutePath());
        
        // 尝试从pom.xml读取模块信息
        try {
            String pomContent = readFileContent(pomFile);
            module.put("artifactId", extractXmlTag(pomContent, "artifactId"));
            module.put("version", extractXmlTag(pomContent, "version"));
            module.put("description", extractXmlTag(pomContent, "description"));
        } catch (Exception e) {
            log.warn("读取模块pom.xml出错: {}", file.getName(), e);
        }
        
        // 分析模块细节
        int[] counts = countFiles(file);
        module.put("javaFiles", counts[0]);
        module.put("totalFiles", counts[1]);
        
        // 统计Java包数量
        int packages = countJavaPackages(file);
        module.put("packageCount", packages);
        
        // 获取子目录结构
        List<Map<String, Object>> children = new ArrayList<>();
        scanDirectoryStructure(file, children, 0, 2); // 最多扫描2层子目录
        module.put("children", children);
        
        return module;
    }
    
    /**
     * 递归扫描目录结构，构建树形结构数据
     * @param dir 目录
     * @param nodeList 节点列表
     * @param currentDepth 当前深度
     * @param maxDepth 最大深度
     */
    private void scanDirectoryStructure(File dir, List<Map<String, Object>> nodeList, int currentDepth, int maxDepth) {
        if (currentDepth > maxDepth || !dir.isDirectory()) {
            return;
        }
        
        File[] files = dir.listFiles(file -> file.isDirectory() && !file.getName().startsWith("."));
        if (files == null) {
            return;
        }
        
        for (File file : files) {
            Map<String, Object> node = new HashMap<>();
            node.put("name", file.getName());
            node.put("path", file.getAbsolutePath());
            
            // 递归获取子目录
            List<Map<String, Object>> children = new ArrayList<>();
            scanDirectoryStructure(file, children, currentDepth + 1, maxDepth);
            if (!children.isEmpty()) {
                node.put("children", children);
            }
            
            nodeList.add(node);
        }
    }
    
    /**
     * 从XML内容中提取指定标签的值
     */
    private String extractXmlTag(String content, String tagName) {
        String startTag = "<" + tagName + ">";
        String endTag = "</" + tagName + ">";
        
        int startIndex = content.indexOf(startTag);
        if (startIndex != -1) {
            startIndex += startTag.length();
            int endIndex = content.indexOf(endTag, startIndex);
            if (endIndex != -1) {
                return content.substring(startIndex, endIndex).trim();
            }
        }
        return "";
    }
    
    /**
     * 读取文件内容
     */
    private String readFileContent(File file) throws IOException {
        return IOUtils.toString(new java.io.FileInputStream(file), "UTF-8");
    }
    
    /**
     * 统计Java包数量
     */
    private int countJavaPackages(File dir) {
        Set<String> packages = new HashSet<>();
        collectJavaPackages(dir, packages);
        return packages.size();
    }
    
    /**
     * 收集Java包
     */
    private void collectJavaPackages(File dir, Set<String> packages) {
        if (dir.isDirectory()) {
            // 检查是否是Java包目录（包含.java文件）
            boolean hasJavaFiles = false;
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isFile() && file.getName().endsWith(".java")) {
                        hasJavaFiles = true;
                        break;
                    }
                }
                
                // 如果有Java文件，添加包路径
                if (hasJavaFiles) {
                    String path = dir.getAbsolutePath();
                    // 同时处理Windows和Mac/Linux路径格式
                    String srcPathWindows = "src\\main\\java";
                    String srcPathUnix = "src/main/java";
                    
                    int srcIndex = path.indexOf(srcPathWindows);
                    if (srcIndex < 0) {
                        srcIndex = path.indexOf(srcPathUnix);
                    }
                    
                    if (srcIndex > 0) {
                        // 确保用正确的长度
                        String matchedPath = path.indexOf(srcPathWindows) >= 0 ? srcPathWindows : srcPathUnix;
                        String packagePath = path.substring(srcIndex + matchedPath.length());
                        // 统一替换所有路径分隔符为Java包格式(点号)
                        packagePath = packagePath.replace('\\', '.').replace('/', '.');
                        // 移除开头的点号(如果有)
                        if (packagePath.startsWith(".")) {
                            packagePath = packagePath.substring(1);
                        }
                        
                        if (!packagePath.isEmpty()) {
                            packages.add(packagePath);
                        }
                    }
                }
                
                // 递归处理子目录
                for (File file : files) {
                    if (file.isDirectory()) {
                        collectJavaPackages(file, packages);
                    }
                }
            }
        }
    }

    /**
     * 递归统计目录中的文件数量
     * @param dir 目录
     * @return 包含Java文件数和总文件数的数组[javaFileCount, totalFileCount]
     */
    private int[] countFiles(File dir) {
        int[] counts = new int[]{0, 0}; // [javaFileCount, totalFileCount]
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        int[] subCounts = countFiles(file);
                        counts[0] += subCounts[0];
                        counts[1] += subCounts[1];
                    } else {
                        counts[1]++;
                        if (file.getName().endsWith(".java")) {
                            counts[0]++;
                        }
                    }
                }
            }
        }
        return counts;
    }

    /**
     * 获取系统环境信息
     */
    @GetMapping("/system-info")
    public AjaxResult getSystemInfo() {
        Map<String, Object> result = new HashMap<>();
        try {
            // 操作系统信息
            result.put("os", System.getProperty("os.name"));
            result.put("osVersion", System.getProperty("os.version"));
            result.put("osArch", System.getProperty("os.arch"));
            
            // Java环境信息
            result.put("javaVersion", System.getProperty("java.version"));
            result.put("javaVendor", System.getProperty("java.vendor"));
            result.put("javaHome", System.getProperty("java.home"));
            result.put("javaClassVersion", System.getProperty("java.class.version"));
            
            // JVM信息
            result.put("jvmName", System.getProperty("java.vm.name"));
            result.put("jvmVersion", System.getProperty("java.vm.version"));
            result.put("jvmVendor", System.getProperty("java.vm.vendor"));
            
            // 用户环境信息
            result.put("userName", System.getProperty("user.name"));
            result.put("userHome", System.getProperty("user.home"));
            result.put("userDir", System.getProperty("user.dir"));
            
            // 文件系统信息
            result.put("fileSeparator", System.getProperty("file.separator"));
            result.put("pathSeparator", System.getProperty("path.separator"));
            result.put("lineSeparator", System.getProperty("line.separator").replace("\n", "\\n").replace("\r", "\\r"));
            
            // 网络信息
            InetAddress localhost = InetAddress.getLocalHost();
            result.put("hostName", localhost.getHostName());
            result.put("hostAddress", localhost.getHostAddress());
            
            // 资源信息
            Runtime runtime = Runtime.getRuntime();
            result.put("availableProcessors", runtime.availableProcessors());
            result.put("totalMemory", runtime.totalMemory());
            result.put("freeMemory", runtime.freeMemory());
            result.put("maxMemory", runtime.maxMemory());
            
            log.info("成功获取系统信息: OS={}, Java={}", 
                    System.getProperty("os.name"), System.getProperty("java.version"));
            
            return success(result);
        } catch (Exception e) {
            log.error("获取系统信息失败", e);
            return error("获取系统信息失败: " + e.getMessage());
        }
    }
}
